//new_shell.c
//ver0.99
//guojt

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#define std_in  0
#define std_out 1
#define std_err 2

char * delete_blank(char * str2);
char *append_blank(char* str3);
void execute_cmd(char *argv[]);

void do_outfile_redirect(char *outfile_name);
void do_infile_redirect(char * infile_name);
void do_parse(char **argv,int cmd_length, int pipe_num,int i,int * pipe_locate);
int main()
{
  char *cmd=(char *)malloc(256*sizeof(char));
  int i=0;
  for(i=0;i<255;i++) cmd[i]='\0';
  //printf("msh@guojt:$");
  fgets(cmd,256,stdin);
  //delete_blank(str2);
  //append_blank(str3);
  //delete_blank(str4);
  int l=0;
  char *argv[10]; 
  char *argv_temp[10];
    l=strlen(cmd);
    l--;
    cmd[l]='\0';
    
   for(i=0;i<10;i++) {
      argv[i]=NULL;
      argv_temp[i]=NULL;
    }
    char* cmd_standied;
    
    //str_temp=delete_blank(cmd);
    cmd_standied =append_blank(delete_blank(cmd));
    char *buf;
    char *infile_name;
    char *outfile_name;
    int cmd_length=0;
    int pipe_num=0;
    int pipe_locate[10];//max pipe number 10
    int have_pipe = 0;
    int have_infile=0;
    int have_outfile=0;
    buf=cmd_standied;
    i=0;
    while((argv_temp[i] = strsep(&buf, " ")) != NULL)
    {    
	i++;
    }
    int k=0;
    i=0;
    for(i=0;argv_temp[i]!=NULL;i++){
      if(strcmp(argv_temp[i],">")==0){
	outfile_name=argv_temp[i+1];
	have_outfile=1;
	//printf("outfile_name:%s\n",outfile_name);
	i+=1;
	continue; 
	}
      
      if(strcmp(argv_temp[i],"<")==0){
	infile_name=argv_temp[i+1];
	have_infile=1;
	//printf("infile_name:%s\n",infile_name);
	i+=1;
	continue;
      }
      if(strcmp(argv_temp[i],"|")==0){
	    
	    pipe_locate[pipe_num]=i;
	    pipe_num++;
	   // printf("the pipe_locate:%d\n",i);
	    have_pipe=1;	
      }  
      argv[k]=argv_temp[i];
      k++;
    }
    cmd_length=k;
//    // printf("i=:%d\n",k);
//     for(i=0;argv[i]!=NULL;i++){
//       printf("%s ",argv[i]);
//     }
//     printf("\n");
  
    if(have_pipe){
      //do_pipe
	 // printf("we have pipe\n");
      
        //do pipe  
        //two pipe 
      int pfds1[2]={-1,-1};
      int pfds2[2]={-1,-1};
       i=0;
      pid_t pid;
      int pnum=0;
      pnum = pipe_num;
       
        for (i=0;i<pipe_num+1;i++)
	{  
	  
	  if(i!=pnum)
	  {
	    if(pnum>0)
	    {
	      if(pipe(pfds1)!=0)
		printf("erro when pipe pfds1\n");
	    }
	  }
	  
	  
	
	  if(fork()==0){
	    
	  //child process
	    
	    if(i!=pnum){
	    close(1);
	    dup2(pfds1[1],1);
	    close(pfds1[0]);
	    close(pfds1[1]);
	    //execvp("ls","ls -l");
	    }
	    
	    if(i!=0){
	    dup2(pfds2[0],0);
	    close(pfds2[0]);
	    close(pfds2[1]);
	    }
	    
	    if(i==0 & have_infile){
	     //do_infile_redirect
	    do_infile_redirect(infile_name);
	      
	    }
	    if(i==pnum & have_outfile){
	      //do_outfile
	    do_outfile_redirect(outfile_name);
	    }
	    
	    //execute
	    do_parse( argv, cmd_length,  pipe_num, i, pipe_locate);
	    
	    
	    exit(1);
	  }
	  
	    if(i!=0)
	    {
	      assert(pfds2[0]!=-1 && pfds2[1]!=-1);
	      close(pfds2[0]);
	      close(pfds2[1]);
	    }
	  pfds2[0]=pfds1[0];
	  pfds2[1]=pfds1[1];
	  
	}
	
	  close(pfds2[0]);
	  close(pfds2[1]);

	  int status;
	  while(waitpid(0,&status,0)>0){}
	    //printf("execute down");
   
    }else{
      
      
      if(have_infile){
	//do_infile_redirect
	do_infile_redirect(infile_name);
      }
      if(have_outfile){
	//do_outfile_redirect
	do_outfile_redirect(outfile_name);
      }
      //execute_cmd
      execute_cmd(argv);
      
    }
    
    
    
    
    
    
  
  
  
}

void do_parse(char **argv,int cmd_length, int pipe_num,int i,int * pipe_locate)
{
      	  int cmdp_l=0;
	  //printf("hello world\n");
	  
	  //for (i=0;i<pipe_num+1;i++){
		if (i==0){
		  cmdp_l=pipe_locate[i]+1;
		  
		}else if(i==pipe_num)
		{
		  cmdp_l=cmd_length-pipe_locate[i-1]-1+1;
		}else
		{
		  cmdp_l=pipe_locate[i]-pipe_locate[i-1]-1+1;
		}
		char *cmdp[cmdp_l];
		int k=0;
		
		for(k=0;k<cmdp_l;k++) cmdp[k]=0;
		
		
	      if(i==0)
	      {
		for(k=0;k<cmdp_l-1;k++)
		{  cmdp[k]=argv[k];
		//printf("cmdp[%d]:%s\n",k,cmdp[k]);
		  
		} 
	      }
	      else{
		for(k=0;k<cmdp_l-1;k++)
		{cmdp[k]=argv[k+pipe_locate[i-1]+1];
		//printf("cmdp[%d]:%s\n",k,cmdp[k]);
		  
		}
	      }
	      
	      execvp(cmdp[0],cmdp);
	      
	     // return cmdp;
}
void do_infile_redirect(char * infile_name)
{
  int fd;
  fd=open(infile_name,O_RDONLY);
  if(fd<0){
    printf("some error in fd\n");
  }else{
    close(std_in);
    dup2(fd,std_in);
  }
  
}
void do_outfile_redirect(char *outfile_name)
{
  int fd;
  fd=open(outfile_name,O_WRONLY|O_CREAT,0777);
  if(fd<0){
    printf("some error in outfile_fd\n");
  }else{
    close(std_out);
    dup2(fd,std_out);
  }
}


char *append_blank(char* str3)
{
    int i=0;
  int k=0;
  //char str[200];
  //char *str =(char *)calloc(100, sizeof(char*));
   char *str=(char *)malloc(256*sizeof(char));
  while(str3[k]!='\0'){
    //do 
    if(str3[k]=='|' & str3[k-1]!=' ' & str3[k+1]!=' '){
      str[i]=' ';
      str[i+1]='|';
      str[i+2]=' ';
      i+=3;
      k++;
    }else
      if(str3[k]=='|' &str3[k-1]!=' ' &str3[k+1]==' '){
	      str[i]=' ';
	      str[i+1]='|';
	      i+=2;
	      k++;
	
      }else if(str3[k]=='|' &str3[k-1]==' ' &str3[k+1]!=' '){
	    str[i]='|';
	    str[i+1]=' ';
	    i+=2;
	    k++;
	
      }else
	if(str3[k]=='<' & str3[k-1]!=' ' & str3[k+1]!=' '){
      str[i]=' ';
      str[i+1]='<';
      str[i+2]=' ';
      i+=3;
      k++;
    }else
      if(str3[k]=='<' &str3[k-1]!=' ' &str3[k+1]==' '){
	      str[i]=' ';
	      str[i+1]='<';
	      i+=2;
	      k++;
	
      }else if(str3[k]=='<' &str3[k-1]==' ' &str3[k+1]!=' '){
	    str[i]='<';
	    str[i+1]=' ';
	    i+=2;
	    k++;
	
      }else
	if(str3[k]=='>' & str3[k-1]!=' ' & str3[k+1]!=' '){
      str[i]=' ';
      str[i+1]='>';
      str[i+2]=' ';
      i+=3;
      k++;
    }else
      if(str3[k]=='>' &str3[k-1]!=' ' &str3[k+1]==' '){
	      str[i]=' ';
	      str[i+1]='>';
	      i+=2;
	      k++;
	
      }else if(str3[k]=='>' &str3[k-1]==' ' &str3[k+1]!=' '){
	    str[i]='>';
	    str[i+1]=' ';
	    i+=2;
	    k++;
      }else{
	    str[i]=str3[k];
	    k++;
	    i++;
	    
	
      }
    
  }
  str[i]='\0';
  //printf("str:%s\n",str);
  return str;
  
}

char * delete_blank(char * str2)
{
  //char str[200];
  char *str=(char *)malloc(256*sizeof(char));
  int k,i;
  int first_is_blank=1;
  k=0;i=0;
  
  k=0;
  while(str2[k]!='\0'){
    if(first_is_blank & str2[k]==' ' ){
      if(str2[k+1]!=' ')
	first_is_blank=0;
      k++;
    }else
    if(str2[k]==' ' & str2[k+1]==' '){
      k++;
    }else{
      first_is_blank=0;
      str[i]=str2[k];
      k++;
      i++;
    }
    
  }
  str[i]='\0';
   //printf("str:%s\n",str);
   return str;
  
}


void execute_cmd(char *argv[])
{
  pid_t pid;
  
  pid=fork();
  if(pid<0){
    printf("some error");
    exit(2);
  }else if(pid==0){
    if(execvp(argv[0],argv)<0)
      printf("some error more");
    exit(3);
  }else
    wait(NULL);
}










